package penguin.masking;

import org.reflections.Reflections;
import org.reflections.util.ConfigurationBuilder;

import java.sql.*;
import java.util.*;

/**
 * @author wuxh
 * @version 1.0.0
 */
public class MaskingReflectionScan {

    Reflections reflections = null;

    public MaskingReflectionScan(String driverScan) {
        Enumeration<Driver> drivers = DriverManager.getDrivers();
        List<String> packages = new ArrayList<>();
        final List<String> scanPackage = driverScan == null ? null: Arrays.asList(driverScan.split(","));
        while (drivers.hasMoreElements()) {
            Class<? extends Driver> aClass = drivers.nextElement().getClass();
            Package aPackage = aClass.getPackage();
            boolean include = false;
            if (scanPackage == null) {
                include = true;
            } else {
                for (String scan : scanPackage) {
                    if (aPackage.getName().startsWith(scan)) {
                        include = true;
                        continue;
                    }
                }
            }
            if (include && !packages.contains(aPackage.getName())) {
                packages.add(aPackage.getName());
            }
        }
        String[] ps = new String[packages.size()];
        packages.toArray(ps);
        reflections = new Reflections(new ConfigurationBuilder().forPackages(ps));
    }

    public List<String> connections() {
        Set<Class<? extends Connection>> subTypes = reflections.getSubTypesOf(Connection.class);
        List<String> classNames = new ArrayList<>();
        for (Class<? extends Connection> subType : subTypes) {
            if (!subType.isInterface()) {
                classNames.add(subType.getName());
            }
        }
        return classNames;
    }

    public List<String> preparedStatements() {
        Set<Class<? extends PreparedStatement>> subTypes = reflections.getSubTypesOf(PreparedStatement.class);
        List<String> classNames = new ArrayList<>();
        for (Class<? extends PreparedStatement> subType : subTypes) {
            if (!subType.isInterface()) {
                classNames.add(subType.getName());
            }
        }
        return classNames;
    }

    public List<String> statements() {
        Set<Class<? extends Statement>> subTypes = reflections.getSubTypesOf(Statement.class);
        List<String> classNames = new ArrayList<>();
        for (Class<? extends Statement> subType : subTypes) {
            if (!subType.isInterface()) {
                classNames.add(subType.getName());
            }
        }
        return classNames;
    }

    public List<String> resultSets() {
        Set<Class<? extends ResultSet>> subTypes = reflections.getSubTypesOf(ResultSet.class);
        List<String> classNames = new ArrayList<>();
        for (Class<? extends ResultSet> subType : subTypes) {
            if (!subType.isInterface()) {
                classNames.add(subType.getName());
            }
        }
        return classNames;
    }
}
